import React, { useEffect, useRef, useState } from 'react';
import { Common } from 'UtilsCommon';
import Base from './base';

const loadEvent = (canvas, property) => {
    const ctx = canvas.getContext('2d');

    const style = window.getComputedStyle(canvas);
    const w = parseFloat(style.width.replace('px', ''));
    const h = parseFloat(style.height.replace('px', ''));

    let undoStack = [];

    const clear = () => {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        property.isShowTip = false;
    };

    property.clear = (isReset) => {
        if (undoStack.length > 0 || isReset) {
            if (isReset) property.enable = true;
            clear();
            undoStack = [];
            showTip();
        }
    };

    property.getImageFile = () => {
        if (undoStack.length === 0) return null;
        return Common.dataURLtoFile(canvas.toDataURL('image/png', 1), "user_sign.png");
    };

    property.undo = () => {
        if (undoStack.length > 0) {
            undoStack.pop();
            if (undoStack.length === 0) {
                clear();
                showTip();
            }
            else undoDraw();
        }
    };

    const undoDraw = () => {
        const image = new Image();
        image.src = undoStack[undoStack.length - 1];
        image.onload = function () {
            clear();
            ctx.drawImage(image, 0, 0);
        };
    };

    property.setValue = (url) => {
        const url2 = url.toLowerCase();
        if (url2.indexOf('http') === 0 && url2.indexOf(window.location.host) < 0) {
            url = window.location.origin + '/image2/get?url=' + encodeURIComponent(url);
        }
        const image = new Image();
        image.src = url;
        image.onload = function () {
            clear();
            let imgWidth = canvas.width;
            let imgHeight = (canvas.width / this.width) * this.height;
            if (imgHeight > canvas.height) {
                imgWidth = (canvas.height / imgHeight) * imgWidth;
                imgHeight = canvas.height;
            }
            const x = (canvas.width - imgWidth) / 2;
            const y = (canvas.height - imgHeight) / 2;

            ctx.drawImage(this, x, y, imgWidth, imgHeight);
        };
    };

    canvas.width = w;
    canvas.height = h;

    let isDrawing = false;
    let isDown = false;

    const obj = {};

    const top = canvas.offsetTop;
    const left = canvas.offsetLeft;

    function showTip() {
        if (property.tipText && !property.isShowTip) {
            const { tipText, tipFontSize, tipFontColor, isBold } = property;
            const size = tipFontSize * window.htmlFontSize;
            ctx.font = (isBold ? 'bold ' : '') + `${size}px 微软雅黑`;
            const w = ctx.measureText(tipText).width;
            const h = size / 2;
            ctx.fillStyle = tipFontColor;
            ctx.fillText(tipText, canvas.width / 2 - w / 2, canvas.height / 2 + h / 2);
            property.isShowTip = true;
        }
    }

    showTip();

    obj.draw = function (p) {
        ctx.lineTo(p.x, p.y);
        ctx.stroke();
    };

    obj.points = [];

    function mousemove(e) {
        if (!isDown) return;

        e.preventDefault && e.preventDefault();

        const p = getXY(e);
        obj.points.push(p);

        requestAnimationFrame(obj.draw.bind(obj, p));

        isDrawing = true;
    }

    function getXY(e) {
        const point = e.touches ? e.touches[0] : e;
        const { pageX, pageY } = point;

        const x = pageX - left;
        const y = pageY - top;
        return { x, y };
    }

    function mousedown(e) {
        if (property.enable === false) return;
        e.preventDefault && e.preventDefault();

        isDown = true;

        if (property.isShowTip) clear();

        const p = getXY(e);

        ctx.beginPath();
        ctx.strokeStyle = property.color;
        ctx.lineWidth = property.lineWidth;
        ctx.moveTo(p.x, p.y);

        obj.points = [];

        if (e.touches) canvas.addEventListener('touchmove', mousemove);
        else canvas.addEventListener('mousemove', mousemove);
    }

    function mouseup(e) {
        if (e.touches) canvas.removeEventListener('touchmove', mousemove);
        else canvas.removeEventListener('mousemove', mousemove);

        if (isDrawing) {
            isDrawing = false;
            if (obj.points.length < 5) {
                if (undoStack.length === 0) {
                    clear();
                    showTip();
                }
                else undoDraw();
            }
            else undoStack.push(canvas.toDataURL());
        }
        else if (isDown && undoStack.length === 0) {
            showTip();
        }

        isDown = false;
    }

    canvas.addEventListener('mousedown', mousedown);
    canvas.addEventListener('mouseup', mouseup);
    document.body.addEventListener('mouseup', mouseup);

    canvas.addEventListener('touchstart', mousedown);
    canvas.addEventListener('touchend', mouseup);
    document.body.addEventListener('touchend', mouseup);
};

export default (props) => {
    const { property } = Base.getProps(props);
    const [isVisible, setIsVisible] = useState(property.isVisible !== false);

    const ele = useRef(null);

    useEffect(() => {
        if (ele.current) {
            loadEvent(ele.current, property);
        }
    }, [property, ele]);

    property.setIsVisible = (v) => { property.isVisible = v; setIsVisible(v); };

    if (!isVisible) return null;

    const { className, style } = property;

    return <div className={className} style={Base.setStyle(style)}>
        <canvas ref={ele} style={{ width: '100%', height: '100%' }}></canvas>
    </div>;
};